#coding=utf-8
# Copyright 2012 Maxim Petrov <maximpetrov@yahoo.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 3 or any later version.

from lxml import etree
import os

class Settings(object):
    """
    Class for operate with application settings
    """

    def __init__(self, repo_dir, main_win):
        """
        Constructor for settings object

        Keyword arguments:
            repo_dir -- root directory of target repository
            main_win -- MainWindow instance
        """

        self.__local_settings_path = main_win.str_to_internal(repo_dir + '/.hg/hgtui.xml', is_filename=True)
        self.__global_settings_path = main_win.str_to_internal(os.path.expanduser('~/.hgtui.xml'), is_filename=True)
        self.reload_settings()
        self.__main_win = main_win

    def reload_settings(self):
        """Function for reread settings files"""

        parser = etree.XMLParser(encoding='utf-8', remove_blank_text=True)
        if os.path.exists(self.__local_settings_path):
            self.__local_settings = etree.parse(self.__local_settings_path, parser)
        else:
            self.__local_settings = etree.ElementTree(etree.Element(u'hgtui'))
        if os.path.exists(self.__global_settings_path):
            self.__global_settings = etree.parse(self.__global_settings_path, parser)
        else:
            self.__global_settings = etree.ElementTree(etree.Element(u'hgtui'))

    def get(self, section, name, is_list=True):
        """
        Get setting value by name from section. At first lookup in local
        settings then in global settings

        Keyword arguments:
            section -- section name should be like class name
            name -- name of setting
            is_list -- value should be list (may contains only 1 element)

        Return value:
            setting value, list of setting values or list of dicts (attribute: value)
        """

        settings = self.__local_settings.xpath(u'/hgtui/' + section + u'/' + name)
        if len(settings) == 0:
            settings = self.__global_settings.xpath(u'/hgtui/' + section + u'/' + name)
            # setting not found
            if len(settings) == 0:
                return None
        # found setting with one value
        if len(settings) == 1 and settings[0].text is not None and not is_list:
            return settings[0].text
        # found empty list
        elif len(settings) == 1 and settings[0].text is None and len(settings[0].attrib) == 0:
            return []
        # found setting with list of values
        else:
            # get values of settings which is not None
            text_values = [s.text for s in settings if s.text is not None]
            # if found any values then return them as list
            if len(text_values) > 0:
                return text_values
            # no values means values is in attributes - return list of dicts
            else:
                return [dict(s.items()) for s in settings]

    def set(self, section, name, values, local=False):
        """
        Set setting value by name in section. By default save in global settings

        Keyword arguments:
            section -- section name should be like class name
            name -- name of setting
            values -- values to set. Can be:
                        1. One value
                        2. List of values (can be empty)
                        3. List of dicts (attribute: value)
            local -- if True save to local settings, otherwise to global
        """

        if values is None:
            return
        if local:
            settings = self.__local_settings
            settings_path = self.__local_settings_path
        else:
            settings = self.__global_settings
            settings_path = self.__global_settings_path
        sect = settings.xpath(u'/hgtui/' + section)
        # if no such section in settings create it
        if len(sect) == 0:
            sect = etree.SubElement(settings.getroot(), section)
        else:
            sect = sect[0]
        # convert one value to list
        if type(values) is not list:
            values = [values]
        s = sect.xpath(name)
        # remove old setting
        for old in s:
            sect.remove(old)
        if type(values) is list and len(values) == 0:
            s_elem = etree.SubElement(sect, name)
        else:
            for v in values:
                s_elem = etree.SubElement(sect, name)
                if type(v) is dict:
                    s_elem.attrib.update(v)
                else:
                    s_elem.text = unicode(v)
        settings.write(self.__main_win.str_to_external(settings_path, is_filename=True), pretty_print=True, encoding='utf-8')
